package com.yiruantong.web.service.impl;

import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjectUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import com.yiruantong.common.core.constant.Constants;
import com.yiruantong.common.core.domain.model.LoginBody;
import com.yiruantong.common.core.domain.model.XcxLoginUser;
import com.yiruantong.common.core.enums.user.UserStatusEnum;
import com.yiruantong.common.core.utils.MessageUtils;
import com.yiruantong.common.core.utils.ValidatorUtils;
import com.yiruantong.common.core.validate.auth.WechatGroup;
import com.yiruantong.common.satoken.utils.LoginHelper;
import com.yiruantong.system.domain.permission.vo.SysUserVo;
import com.yiruantong.system.domain.tenant.SysClient;
import com.yiruantong.web.domain.vo.LoginVo;
import com.yiruantong.web.service.IAuthStrategy;
import com.yiruantong.web.service.SysLoginService;
import org.springframework.stereotype.Service;

/**
 * 邮件认证策略
 *
 * @author YiRuanTong
 */
@Slf4j
@Service("xcx" + IAuthStrategy.BASE_NAME)
@RequiredArgsConstructor
public class XcxAuthStrategy implements IAuthStrategy {

  private final SysLoginService loginService;

  @Override
  public void validate(LoginBody loginBody) {
    ValidatorUtils.validate(loginBody, WechatGroup.class);
  }

  @Override
  public LoginVo login(String clientId, LoginBody loginBody, SysClient client) {
    // xcxCode 为 小程序调用 wx.login 授权后获取
    String xcxCode = loginBody.getXcxCode();
    // todo 以下自行实现
    // 校验 appid + appsrcret + xcxCode 调用登录凭证校验接口 获取 session_key 与 openid
    String openid = "";
    // 框架登录不限制从什么表查询 只要最终构建出 LoginUser 即可
    SysUserVo user = loadUserByOpenid(openid);

    // 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了
    XcxLoginUser loginUser = new XcxLoginUser();
    loginUser.setTenantId(user.getTenantId());
    loginUser.setUserId(user.getUserId());
    loginUser.setUsername(user.getUserName());
    loginUser.setNickname(user.getNickName());
    loginUser.setUserType(user.getUserType());
    loginUser.setOpenid(openid);

    SaLoginModel model = new SaLoginModel();
    model.setDevice(client.getDeviceType());
    // 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置
    // 例如: 后台用户30分钟过期 app用户1天过期
    model.setTimeout(client.getTimeout());
    model.setActiveTimeout(client.getActiveTimeout());
    model.setExtra(LoginHelper.CLIENT_ID, clientId);
    model.setExtra(LoginHelper.CLIENT_KEY, client.getClientKey());
    // 生成token
    LoginHelper.login(loginUser, model);

    loginService.recordLogininfor(loginUser.getTenantId(), user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
    loginService.recordLoginInfo(user.getUserId());

    LoginVo loginVo = new LoginVo();
    loginVo.setAccessToken(StpUtil.getTokenValue());
    loginVo.setExpireIn(StpUtil.getTokenTimeout());
    loginVo.setClientId(clientId);
    loginVo.setOpenid(openid);
    return loginVo;
  }

  private SysUserVo loadUserByOpenid(String openid) {
    // 使用 openid 查询绑定用户 如未绑定用户 则根据业务自行处理 例如 创建默认用户
    // todo 自行实现 userService.selectUserByOpenid(openid);
    SysUserVo user = new SysUserVo();
    if (ObjectUtil.isNull(user)) {
      log.info("登录用户：{} 不存在.", openid);
      // todo 用户不存在 业务逻辑自行实现
    } else if (UserStatusEnum.DISABLE.getCode().equals(user.getEnable())) {
      log.info("登录用户：{} 已被停用.", openid);
      // todo 用户已被停用 业务逻辑自行实现
    }
    return user;
  }

}
